<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
  // 函数
    // 1. 函数声明: 函数提升
    // fn1('lisi', 23);
    // function fn1(name, age){
    //     console.log(name, age);
    // }   

  // 2. 函数表达式
    let fn2 = function fn3(name, age) {
        // console.log(name, age);
        // fn3 此时，fn3只能在函数的内部使用，一般可以用来做递归操作。
    }
    // fn2('lisi', 23);
    
  // 递归案例：求10的阶乘
    // 10! = 10*9*8...*1
    // function factorial(n){
    //     if(n == 1){
    //         return 1;
    //     }
    //     return n * factorial(n - 1);
    // }
    // console.log(factorial(10)); // => 10! = 10*9*8...*1 = 

    // let factorial1 = function factorial2(n) {
    //     if (n == 1) {
    //         return 1;
    //     }
    //     return n * factorial2(n - 1);
    // }
    // console.log(factorial1(10));

    // let aa = function(n) {
    //     if (n == 1) {
    //         return 1;
    //     }
    //     return n * arguments.callee(n - 1); // callee:在函数内部，用来指代函数自己 aa == arguments.callee
    // }
    // console.log(aa(10));

    // 函数式编程!!!
    // 1. 函数可以做为一个值，赋值给一个变量
    // 2. 函数可以做为一个值，在另外一个函数中返回
    // 3. 函数可以做为一个值，传给另外一个函数

    // 对象(object)
    // 什么是对象：everything is object， 一切皆对象
    // 属性（特征）和方法（行为）
    // 面向对象（Object-Oriented）
    // OOA（analysis）
    // OOD（design）
    // OOP（programming）

    // 人到图书馆借书
    // 人
        // 属性：姓名、身份证号
        // 方法：
    // 书
        // 属性：书名、书号
        // 方法：
    // 图书馆
        // 属性：馆名、地址
        // 方法：
    // 管理员
        // 属性：
        // 方法：登记()

    // 创建对象
    // 1. new Object()
    // let person = new Object();
    // person.name = 'lisi';
    // person.idCard = '23456789';

    // 2. {}对象直接量(literal)
    // let book = {
    //     name: '大学英语四级',
    //     isbn: 'qwertyu23456'
    // };

    // let library = {
    //     name: '学府书店',
    //     addr: '学府路...'
    // 

    // let manager = {
    //     register: function(personName, personIdCard, bookName, bookIsbn){
    //          console.log("姓名：" + personName + ", 身份证号：" + personIdCard + ", 书名：" + bookName + ", 书号：" + bookIsbn);
    //      }
    //     register: function(person, book){
    //         console.log("姓名：" + person.name + ", 身份证号：" + person.idCard + ", 书名：" + book.name + ", 书号：" + book.isbn);
    //     }
    // };

    // manager.register(person, book);

    // 3. new 类名
    // function Person(name, age){ // 构造函数
    //     this.name = name;
    //     this.age = age;
    //     console.log(this);
    // }

    // let person1 = new Person('lisi', 23);

    // console.log(person1);

    // Person('lisi', 23);

    // 例子1
    // let o1 = {
    //   name: 'lisi'
    // };
    // let o2 = o1;

    // o2.name = 'wangwu';

    // console.log(o1.name); // => 'wangwu'

    // 例子2
    // let o1 = {
    //   name: 'lisi'
    // };
    // let o2 = o1;

    // o1.name = 'wangwu';

    // console.log(o2.name); // => 'wangwu'

    // 例子3
    // let a = 5;
    // let b = a;
    // a = 6;
    // console.log(b); // => '5'

    // 例子4
    // let a = b = 5;
    // b = 6;
    // console.log(b); // => '5'

    // 例子5
    // function fn(){
    //   var a = b = 5; // var a = 5;b = 5;只有a定义var，b没有
    // }
    // fn();
    // console.log(a); // a is not definded
    // console.log(b); // 5

    // 例子6
    // function fn(x){ //函数的形参是局部变量
    //   x = 6; //参数
    //   console.log(x);
    // }
    // fn(5);
    // console.log(x);// x is not definded，因为x是形参，也是局部变量

    // 例子7
    function fn(x){ //函数的形参是局部变量
      x = 6; //参数
      console.log(x);
    }
    var a = 5;
    fn(a);

    console.log(a); // a还是5

    // 例子8
    function fn(o1){
      o1.name = 'wangwu'
    }
    let o = {
      name: 'lisi'
    }
    fn(o);
    console.log(o.name); // o.name跟着改成了wangwu

  </script>
</body>
</html>